import codecs
import configparser
import platform
import os
import logging
import re
import winreg as winreg
from tools_pack import global_shared
import itertools
loger=logging.getLogger("metas")
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

def get_ini_value(node,options):
    cc = configparser.ConfigParser()
    cc.readfp(codecs.open(os.path.join(BASE_DIR,"config.ini"), "r", "utf-8-sig"))
    try:
        value= cc.get(node,options)
    except Exception as e:
        value=""
    return value

def set_ini_value(node,options,value):
    cc = configparser.ConfigParser()
    cc.readfp(codecs.open(os.path.join(BASE_DIR,"config.ini"), "r", "utf-8-sig"))
    cc.set(node,options,value.decode("utf-8-sig"))
    with open("config.ini", "w+") as f:
        cc.write(f)
    return True


def get_arduino_command(arduino_cmd):
    """Attempt to find or guess the path to the Arduino binary."""

    arduino_catalogue_x64 = get_ini_value('metas_conf', 'arduino_catalogue_x64')
    arduino_catalogue_x86 = get_ini_value('metas_conf', 'arduino_catalogue_x86')
    arduino_debug_catalogue_x64 = get_ini_value('metas_conf', 'arduino_debug_catalogue_x64')
    arduino_debug_catalogue_x86 = get_ini_value('metas_conf', 'arduino_debug_catalogue_x86')

    if not arduino_cmd:
        # print platform.system()
        if platform.system() == "Darwin":
            arduino_cmd_guesses = ["/Applications/Arduino.app/Contents/MacOS/Arduino"]
        elif platform.system() == "Windows":
            arduino_cmd_guesses = [arduino_debug_catalogue_x64,
                                   arduino_debug_catalogue_x86,
                                  arduino_catalogue_x64,
                                   arduino_catalogue_x86
                                   ]
        else:
            arduino_cmd_guesses = []
        for guess in arduino_cmd_guesses:
            # print os.path.exists(guess)
            # print guess
            if os.path.exists(guess):
                loger.info("Found Arduino command at %s", guess)
                arduino_cmd = guess
                break
        else:
            loger.info("Couldn't find Arduino command; hoping it's on the path!")
            arduino_cmd = "arduino"
            key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, "Arduino file\\shell\\open\\command")
            try:
                i=0
                while 1:
                    #EnumValue方法用来枚举键值，EnumKey用来枚举子键
                    name,value,type = winreg.EnumValue(key,i)
                    r = r'\"(?P<arduino_path>.*\.exe).*'
                    path = re.match(r, value)
                    if path != None:
                        arduino_cmd = path.group("arduino_path")[:-4] + '_debug.exe'
                    i+=1
            except WindowsError as e:
                pass

    return arduino_cmd


def guess_port_name():
    """Attempt to guess a port name that we might find an Arduino on."""
    portname = None
    if platform.system() == "Windows":
        try:
            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM")
        except Exception as e:
            loger.warning(e)
            return ""
        # We'll guess it's the last COM port.
        for i in itertools.count():
            try:
                portname = winreg.EnumValue(key, i)[1]
            except WindowsError:
                break
        connect_type=get_ini_value("connect","type")
        if connect_type=="0":
            portname=get_usb_port()
        elif connect_type=="1":
            portname=get_bluetooth_port()
        else:
            portname=get_usb_port()

    else:
        # We'll guess it's the first non-bluetooth tty. or cu. prefixed device
        ttys = [filename for filename in os.listdir("/dev")
                if (filename.startswith("tty.") or filename.startswith("cu."))
                and not "luetooth" in filename]
        ttys.sort(key=lambda k:(k.startswith("cu."), k))
        if ttys:
            portname = "/dev/" + ttys[0]
    loger.info("Guessing port name as %s", portname)
    return portname


def get_bluetooth_port():
    """
    获取蓝牙的传出端口
    :return: 端口号 type int
    """
    port_dict={}
    try:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM")
    except Exception as e:
        loger.warning(e)
        return None
    try:
        i = 0
        while 1:
            # EnumValue方法用来枚举键值，EnumKey用来枚举子键
            name, value, ptype = winreg.EnumValue(key, i)
            bluetooth_name = r'.+BthModem([0-9]+)'
            name_ma = re.match(bluetooth_name, name)
            if name_ma!=None:
                value_ma=re.match(r'.+(\d+)',value)
                if value_ma!=None:
                    port_dict[int(name_ma.group(1))]=value
            i += 1
    except WindowsError as e:
        pass
    if list(port_dict.keys()).__len__()>0:
        port_sort=list(port_dict.keys())
        port_sort.sort()
        return port_dict[port_sort[0]]
    else:
        return None


def get_usb_port():
    """
    获取usb的传出端口
    :return: 端口号 type int
    """
    port_dict={}
    try:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM")
    except Exception as e:
        loger.warning(e)
        return None
    try:
        i = 0
        while 1:
            # EnumValue方法用来枚举键值，EnumKey用来枚举子键
            name, value, ptype = winreg.EnumValue(key, i)
            bluetooth_name = r'.+VCP([0-9]+)'
            name_ma = re.match(bluetooth_name, name)
            if name_ma!=None:
                return value
            i += 1
    except WindowsError as e:
        pass
        return None


def get_all_port():
    """
    获取现有的所有端口
    :return: type list
    """
    com_list=[]
    try:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM")
    except Exception as e:
        loger.warning(e)
        return com_list
    try:
        i = 0
        while 1:
            # EnumValue方法用来枚举键值，EnumKey用来枚举子键
            name, value, ptype = winreg.EnumValue(key, i)
            com_list.append(value)
            i += 1
    except WindowsError as e:
        pass
    return com_list


def usb_check_port_connect():
    """
    检测usb转串口是否在连接
    :return: bool  true 连接中   false 断开
    """
    try:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM")
    except Exception as e:
        loger.warning(e)
        return False
    port_re = r'.+VCP([0-9]+)'
    port_connect=False
    use_port=global_shared.get_value('tmp_user_use_port',None)
    for i in itertools.count():
        try:
            name, value, ptype = winreg.EnumValue(key, i)
            port_obj=re.match(port_re,name)
            if port_obj != None:
                if use_port!=None:
                    if value==use_port:
                        port_connect=True
                        break
                else:
                    port_connect=True
                    break

        except WindowsError:
            break
    return port_connect

def bluetooth_check_port_connect():
    """
    检测蓝牙转串口是否在连接
    :return: bool  true 连接中   false 断开
    """
    try:
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM")
    except Exception as e:
        loger.warning(e)
        return False
    port_re = r'.+BthModem([0-9]+)'
    port_connect = False
    use_port = global_shared.get_value('tmp_user_use_port', None)
    for i in itertools.count():
        try:
            name, value, ptype = winreg.EnumValue(key, i)
            port_obj = re.match(port_re, name)
            if port_obj != None:
                if use_port!=None:
                    if value==use_port:
                        port_connect=True
                        break
                else:
                    port_connect=True
                    break
        except WindowsError:
            break
    return port_connect

if __name__ == '__main__':
    print(get_all_port())